
namespace Derm.Render.Shaders.Light {

	/// <summary>
	/// Shader source generated from LightState shader source file.
	/// </summary>
	public class LightStateShader : ShaderObject
	{
		#region Constructors

		/// <summary>
		/// Construct a LightStateShader specifying the shader stage.
		/// </summary>
		/// <param name="sType">
		/// A <see cref="Stage"/> indicating the shader stage of this LightStateShader.
		/// </param>
		public LightStateShader(Stage sType) : base(sType, "Derm/Shaders/Light/LightState") { }

		/// <summary>
		/// A string that identifies this ShaderObject implementation in ShaderLibraryConfiguration.
		/// </summary>
		public static readonly string LibraryId = "Derm.Light.LightStateShader";

		#endregion

		#region ShaderObject Overrides

		/// <summary>
		/// The source string read from Derm/Shaders/Light/LightState.
		/// </summary>
		protected override string[] Source { get { return (sShaderSource); } }

		/// <summary>
		/// The source string read from Derm/Shaders/Light/LightState.
		/// </summary>
		private static readonly string[] sShaderSource = new string[] {
			"",
			"//  Copyright (C) 2011-2012 Luca Piccioni",
			"// ",
			"//  This program is free software: you can redistribute it and/or modify",
			"//  it under the terms of the GNU General Public License as published by",
			"//  the Free Software Foundation, either version 3 of the License, or",
			"//  (at your option) any later version.",
			"// ",
			"//  This program is distributed in the hope that it will be useful,",
			"//  but WITHOUT ANY WARRANTY; without even the implied warranty of",
			"//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the",
			"//  GNU General Public License for more details.",
			"// ",
			"//  You should have received a copy of the GNU General Public License",
			"//  along with this program.  If not, see <http://www.gnu.org/licenses/>.",
			"",
			"#include </Derm/Shaders/Light/MaterialState>",
			"",
			"// @BeginInterface",
			"",
			"// The light model applied",
			"struct ds_LightModelType",
			"{",
			"	// Two sided lighting",
			"	bool TwoSided;",
			"	// The ambient lighting.",
			"	vec4 AmbientLighting;",
			"};",
			"",
			"// Light structure",
			"struct ds_LightType",
			"{",
			"	// Light ambient color (used by all lights).",
			"	vec4 AmbientColor;",
			"	// Light diffuse color (used by all lights).",
			"	vec4 DiffuseColor;",
			"	// Light specular color (used by all lights).",
			"	vec4 SpecularColor;",
			"	// The light position vector (used by directional and spot lights).",
			"	vec3 Direction;",
			"	// The light position vector (used by point and spot lights).",
			"	vec4 Position;",
			"	// The light half-vector (used by directional lights).",
			"	vec3 HalfVector;",
			"	// The light attenuation factors (X: constant; Y: linear; Z: quadratic; used by point and spot lights).",
			"	vec3 AttenuationFactors;",
			"	// The spot fall-off parameters (X: fall-off angle in degrees; Y: fall-off exponent, used by spot lights).",
			"	vec2 FallOff;",
			"};",
			"",
			"// If not overriden, define the maximum number of lights",
			"#ifndef DS_MAX_LIGHTS_COUNT",
			"#define DS_MAX_LIGHTS_COUNT			8",
			"#endif",
			"",
			"// The light model",
			"uniform ds_LightModelType ds_LightModel;",
			"",
			"// The lights",
			"uniform ds_LightType ds_Light[DS_MAX_LIGHTS_COUNT];",
			"",
			"// The enabled lights count",
			"uniform int ds_LightsCount;",
			"",
			"// Compute the color contribution of all enabled lights",
			"void ComputeLightContributions(vec3 normal, vec4 eyePosition, inout vec4 ambient, inout vec4 diffuse);",
			"",
			"// Compute the color contribution of all enabled lights",
			"void ComputeLightContributions(vec3 normal, vec4 eyePosition, float materialShininess, inout vec4 specular);",
			"",
			"// Compute the color contribution of all enabled lights",
			"void ComputeLightContributions(vec3 normal, vec4 eyePosition, float materialShininess, inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);",
			"",
			"// @EndInterface",
			"",
			"void ComputeDirectionalLight(int lightIdx, vec3 normal, inout vec4 ambient, inout vec4 diffuse);",
			"void ComputeDirectionalLight(int lightIdx, vec3 normal, float materialShininess, inout vec4 specular);",
			"void ComputeDirectionalLight(int lightIdx, vec3 normal, float materialShininess, inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);",
			"",
			"void ComputePointLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, inout vec4 ambient, inout vec4 diffuse);",
			"void ComputePointLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, float materialShininess, inout vec4 specular);",
			"void ComputePointLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, float materialShininess, inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);",
			"",
			"void ComputeSpotLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, inout vec4 ambient, inout vec4 diffuse);",
			"void ComputeSpotLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, float materialShininess, inout vec4 specular);",
			"void ComputeSpotLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, float materialShininess, inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);",
			"",
			"void ComputeLightContributions(in vec3 normal, vec4 eyePosition, float materialShininess, inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)",
			"{",
			"	vec3 ecPosition3 = vec3(eyePosition) / eyePosition.w;		// Local viewer",
			"",
			"	for (int i = 0; i < ds_LightsCount; i++) {",
			"		if (ds_Light[i].Position.w == 0.0)",
			"			ComputeDirectionalLight(i, normal, materialShininess, ambient, diffuse, specular);",
			"		else if (ds_Light[i].FallOff[0] == 180.0)",
			"			ComputePointLight(i, -normalize(ecPosition3), ecPosition3, normal, materialShininess, ambient, diffuse, specular);",
			"#if 0",
			"		else",
			"			ComputeSpotLight(i, normal, materialShininess, ambient, diffuse, specular);",
			"#endif",
			"	}",
			"",
			"	ambient = ambient / vec4(ds_LightsCount, ds_LightsCount, ds_LightsCount, 1.0);",
			"	diffuse = diffuse / vec4(ds_LightsCount, ds_LightsCount, ds_LightsCount, 1.0); ",
			"	specular = specular / vec4(ds_LightsCount, ds_LightsCount, ds_LightsCount, 1.0); ",
			"}",
			"",
			"void ComputeLightContributions(in vec3 normal, vec4 eyePosition, inout vec4 ambient, inout vec4 diffuse)",
			"{",
			"	vec3 ecPosition3 = vec3(eyePosition) / eyePosition.w;		// Local viewer",
			"",
			"	for (int i = 0; i < ds_LightsCount; i++) {",
			"		if (ds_Light[i].Position.w == 0.0)",
			"			ComputeDirectionalLight(i, normal, ambient, diffuse);",
			"		else if (ds_Light[i].FallOff[0] == 180.0)",
			"			ComputePointLight(i, -normalize(ecPosition3), ecPosition3, normal, ambient, diffuse);",
			"#if 0",
			"		else",
			"			ComputeSpotLight(i, normal, ambient, diffuse);",
			"#endif",
			"	}",
			"}",
			"",
			"void ComputeLightContributions(in vec3 normal, float materialShininess, inout vec4 specular)",
			"{",
			"",
			"}",
			"",
			"/// -----------------------------------------------------------------------------------------------",
			"/// Light utilities",
			"/// -----------------------------------------------------------------------------------------------",
			"",
			"// Compute the attenuation factor",
			"float ComputeAttenuationFactor(int lightIdx, float distance)",
			"{",
			"	// Compute attenuation",
			"	return 1.0 / (",
			"		ds_Light[lightIdx].AttenuationFactors[0] +",
			"		ds_Light[lightIdx].AttenuationFactors[1] * distance +",
			"		ds_Light[lightIdx].AttenuationFactors[2] * distance * distance",
			"		);",
			"}",
			"",
			"/// -----------------------------------------------------------------------------------------------",
			"/// Directional light",
			"/// -----------------------------------------------------------------------------------------------",
			"",
			"/// <summary>",
			"/// Compute a directional light contribution for ambient and diffuse components.",
			"/// <summary/>",
			"void ComputeDirectionalLight(int lightIdx, vec3 normal, inout vec4 ambient, inout vec4 diffuse)",
			"{",
			"	// Dot-product between normal and light direction",
			"	float dotNL = max(0.0, dot(normal, normalize(ds_Light[lightIdx].Direction)));",
			"",
			"	// Emit light color contribution",
			"	ambient  += ds_Light[lightIdx].AmbientColor;",
			"	diffuse  += ds_Light[lightIdx].DiffuseColor * dotNL;",
			"}",
			"",
			"/// <summary>",
			"/// Compute a directional light contribution for specular only component.",
			"/// <summary/>",
			"void ComputeDirectionalLight(int lightIdx, vec3 normal, float materialShininess, inout vec4 specular)",
			"{",
			"	// Dot-product between normal and light direction",
			"	float dotNL = max(0.0, dot(normal, normalize(ds_Light[lightIdx].Direction)));",
			"	// Dot-product between normal and light half-vector",
			"	float dotNH = max(0.0, dot(normal, normalize(vec3(ds_Light[lightIdx].HalfVector))));",
			"",
			"	// Compute specular power factor",
			"	float powerFactor = 0.0;",
			"	if (dotNL != 0) {",
			"		// Effective power factor",
			"		powerFactor = pow(dotNH, materialShininess);",
			"	}",
			"",
			"	// Emit light color contribution",
			"	specular += ds_Light[lightIdx].SpecularColor * powerFactor;",
			"}",
			"",
			"/// <summary>",
			"/// Compute a directional light contribution for ambient, diffuse and specular components.",
			"/// <summary/>",
			"void ComputeDirectionalLight(int lightIdx, vec3 normal, float materialShininess, inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)",
			"{",
			"	// Dot-product between normal and light direction",
			"	float dotNL = max(0.0, dot(normal, normalize(ds_Light[lightIdx].Direction)));",
			"	// Dot-product between normal and light half-vector",
			"	float dotNH = max(0.0, dot(normal, normalize(vec3(ds_Light[lightIdx].HalfVector))));",
			"",
			"	// Compute specular power factor",
			"	float powerFactor = 0.0;",
			"	if (dotNL != 0) {",
			"		// Effective power factor",
			"		powerFactor = pow(dotNH, materialShininess);",
			"	}",
			"",
			"	// Emit light color contribution",
			"	ambient  += ds_Light[lightIdx].AmbientColor;",
			"	diffuse  += ds_Light[lightIdx].DiffuseColor * dotNL;",
			"	specular += ds_Light[lightIdx].SpecularColor * powerFactor;",
			"}",
			"",
			"/// -----------------------------------------------------------------------------------------------",
			"/// Point light",
			"/// -----------------------------------------------------------------------------------------------",
			"",
			"/// <summary>",
			"/// Compute a point light contribution for ambient and diffuse components.",
			"/// <summary/>",
			"void ComputePointLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, inout vec4 ambient, inout vec4 diffuse)",
			"{",
			"	// Compute vector from surface to light position",
			"	vec3 lightVector = vec3(ds_Light[lightIdx].Position) - ecPos3;",
			"	// Compute attenuation",
			"	float attenuation = ComputeAttenuationFactor(lightIdx, length(lightVector));",
			"	",
			"	// Dot-product between normal and light direction",
			"	float dotVP = max(0.0, dot(normal, normalize(lightVector)));",
			"",
			"	// Emit light color contribution",
			"	ambient  += ds_Light[lightIdx].AmbientColor * attenuation;",
			"	diffuse  += ds_Light[lightIdx].DiffuseColor * dotVP * attenuation;",
			"}",
			"",
			"/// <summary>",
			"/// Compute a point light contribution for ambient, diffuse and specular components.",
			"/// <summary/>",
			"void ComputePointLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, float materialShininess, inout vec4 specular)",
			"{",
			"	// Compute vector from surface to light position",
			"	vec3 lightVector = vec3(ds_Light[lightIdx].Position) - ecPos3;",
			"	// Compute attenuation",
			"	float attenuation = ComputeAttenuationFactor(lightIdx, length(lightVector));",
			"	",
			"	// Normalize vector from surface to light position",
			"	lightVector = normalize(lightVector);",
			"",
			"	// Compute the half-vector",
			"	vec3 halfVector = normalize(lightVector + eye);",
			"	// Dot-product between normal and light direction",
			"	float dotVP = max(0.0, dot(normal, lightVector));",
			"	// Dot-product between normal and light half-vector",
			"	float dotHV = max(0.0, dot(normal, halfVector));",
			"",
			"	// Compute specular power factor",
			"	float powerFactor = 0.0;",
			"	if (dotVP != 0)",
			"		powerFactor = pow(dotHV, materialShininess);",
			"",
			"	// Emit light color contribution",
			"	specular += ds_Light[lightIdx].SpecularColor * powerFactor * attenuation;",
			"}",
			"",
			"/// <summary>",
			"/// Compute a point light contribution for ambient, diffuse and specular components.",
			"/// <summary/>",
			"void ComputePointLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, float materialShininess, inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)",
			"{",
			"	// Compute vector from surface to light position",
			"	vec3 lightVector = vec3(ds_Light[lightIdx].Position) - ecPos3;",
			"	// Compute attenuation",
			"	float attenuation = ComputeAttenuationFactor(lightIdx, length(lightVector));",
			"	",
			"	// Normalize vector from surface to light position",
			"	lightVector = normalize(lightVector);",
			"",
			"	// Compute the half-vector",
			"	vec3 halfVector = normalize(lightVector + eye);",
			"	// Dot-product between normal and light direction",
			"	float dotVP = max(0.0, dot(normal, lightVector));",
			"	// Dot-product between normal and light half-vector",
			"	float dotHV = max(0.0, dot(normal, halfVector));",
			"",
			"	// Compute specular power factor",
			"	float powerFactor = 0.0;",
			"	if (dotVP != 0)",
			"		powerFactor = pow(dotHV, materialShininess);",
			"",
			"	// Emit light color contribution",
			"	ambient  += ds_Light[lightIdx].AmbientColor * attenuation;",
			"	diffuse  += ds_Light[lightIdx].DiffuseColor * dotVP * attenuation;",
			"	specular += ds_Light[lightIdx].SpecularColor * powerFactor * attenuation;",
			"}",
			"",
			"/// -----------------------------------------------------------------------------------------------",
			"/// Spot light",
			"/// -----------------------------------------------------------------------------------------------",
			"",
			"void ComputeSpotLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, inout vec4 ambient, inout vec4 diffuse)",
			"{",
			"",
			"}",
			"",
			"void ComputeSpotLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, float materialShininess, inout vec4 specular)",
			"{",
			"",
			"}",
			"",
			"void ComputeSpotLight(int lightIdx, vec3 eye, vec3 ecPos3, vec3 normal, float materialShininess, inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)",
			"{",
			"	// Compute vector from surface to light position",
			"	vec3 lightVector = vec3(ds_Light[lightIdx].Position) - ecPos3;",
			"	// Compute attenuation",
			"	float attenuation = ComputeAttenuationFactor(lightIdx, length(lightVector));",
			"	",
			"	// Normalize vector from surface to light position",
			"	lightVector = normalize(lightVector);",
			"",
			"	// Check whether position in inside the spot",
			"	float dotSpot = dot(-lightVector, normalize(ds_Light[lightIdx].Direction));",
			"	if (dotSpot < ds_Light[lightIdx].FallOff[0])",
			"		return;		/* No contribution */",
			"	else",
			"		attenuation *= pow(dotSpot, ds_Light[lightIdx].FallOff[1]);",
			"",
			"	// Compute the half-vector",
			"	vec3 halfVector = normalize(lightVector + eye);",
			"	// Dot-product between normal and light direction",
			"	float dotVP = max(0.0, dot(normal, lightVector));",
			"	// Dot-product between normal and light half-vector",
			"	float dotHV = max(0.0, dot(normal, halfVector));",
			"",
			"	// Compute specular power factor",
			"	float powerFactor = 0.0;",
			"	if (dotVP != 0)",
			"		powerFactor = pow(dotHV, ds_FrontMaterial.Shininess);",
			"",
			"	// Emit light color contribution",
			"	ambient  += ds_Light[lightIdx].AmbientColor * attenuation;",
			"	diffuse  += ds_Light[lightIdx].DiffuseColor * dotVP * attenuation;",
			"	specular += ds_Light[lightIdx].SpecularColor * powerFactor * attenuation;",
			"}",
		};

		#endregion
	}

	/// <summary>
	/// Shader include extracted from LightState.
	/// </summary>
	public class LightStateIncludeObject : ShaderInclude
	{
		#region Constructors

		/// <summary>
		/// Construct a LightStateIncludeObject.
		/// </summary>
		public LightStateIncludeObject() : base("/Derm/Shaders/Light/LightState", sShaderInclude) { }

		#endregion

		#region ShaderInclude Source Code

		/// <summary>
		/// The shader include source code.
		/// </summary>
		private static readonly string[] sShaderInclude = new string[] {
			"// The light model applied\n",
			"struct ds_LightModelType\n",
			"{\n",
			"// Two sided lighting\n",
			"bool TwoSided;\n",
			"// The ambient lighting.\n",
			"vec4 AmbientLighting;\n",
			"};\n",
			"// Light structure\n",
			"struct ds_LightType\n",
			"{\n",
			"// Light ambient color (used by all lights).\n",
			"vec4 AmbientColor;\n",
			"// Light diffuse color (used by all lights).\n",
			"vec4 DiffuseColor;\n",
			"// Light specular color (used by all lights).\n",
			"vec4 SpecularColor;\n",
			"// The light position vector (used by directional and spot lights).\n",
			"vec3 Direction;\n",
			"// The light position vector (used by point and spot lights).\n",
			"vec4 Position;\n",
			"// The light half-vector (used by directional lights).\n",
			"vec3 HalfVector;\n",
			"// The light attenuation factors (X: constant; Y: linear; Z: quadratic; used by point and spot lights).\n",
			"vec3 AttenuationFactors;\n",
			"// The spot fall-off parameters (X: fall-off angle in degrees; Y: fall-off exponent, used by spot lights).\n",
			"vec2 FallOff;\n",
			"};\n",
			"// If not overriden, define the maximum number of lights\n",
			"#ifndef DS_MAX_LIGHTS_COUNT\n",
			"#define DS_MAX_LIGHTS_COUNT			8\n",
			"#endif\n",
			"// The light model\n",
			"uniform ds_LightModelType ds_LightModel;\n",
			"// The lights\n",
			"uniform ds_LightType ds_Light[DS_MAX_LIGHTS_COUNT];\n",
			"// The enabled lights count\n",
			"uniform int ds_LightsCount;\n",
			"// Compute the color contribution of all enabled lights\n",
			"void ComputeLightContributions(vec3 normal, vec4 eyePosition, inout vec4 ambient, inout vec4 diffuse);\n",
			"// Compute the color contribution of all enabled lights\n",
			"void ComputeLightContributions(vec3 normal, vec4 eyePosition, float materialShininess, inout vec4 specular);\n",
			"// Compute the color contribution of all enabled lights\n",
			"void ComputeLightContributions(vec3 normal, vec4 eyePosition, float materialShininess, inout vec4 ambient, inout vec4 diffuse, inout vec4 specular);\n",
		};

		#endregion
	}

	/// <summary>
	/// Shader source generated from LambertShading shader source file.
	/// </summary>
	public class LambertShading : ShaderObject
	{
		#region Constructors

		/// <summary>
		/// Construct a LambertShading specifying the shader stage.
		/// </summary>
		/// <param name="sType">
		/// A <see cref="Stage"/> indicating the shader stage of this LambertShading.
		/// </param>
		public LambertShading(Stage sType) : base(sType, "Derm/Shaders/Light/LambertShading") { }

		/// <summary>
		/// A string that identifies this ShaderObject implementation in ShaderLibraryConfiguration.
		/// </summary>
		public static readonly string LibraryId = "Derm.Light.LambertShading";

		#endregion

		#region ShaderObject Overrides

		/// <summary>
		/// The source string read from Derm/Shaders/Light/LambertShading.
		/// </summary>
		protected override string[] Source { get { return (sShaderSource); } }

		/// <summary>
		/// The source string read from Derm/Shaders/Light/LambertShading.
		/// </summary>
		private static readonly string[] sShaderSource = new string[] {
			"",
			"//  Copyright (C) 2012 Luca Piccioni",
			"// ",
			"//  This program is free software: you can redistribute it and/or modify",
			"//  it under the terms of the GNU General Public License as published by",
			"//  the Free Software Foundation, either version 3 of the License, or",
			"//  (at your option) any later version.",
			"// ",
			"//  This program is distributed in the hope that it will be useful,",
			"//  but WITHOUT ANY WARRANTY; without even the implied warranty of",
			"//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the",
			"//  GNU General Public License for more details.",
			"// ",
			"//  You should have received a copy of the GNU General Public License",
			"//  along with this program.  If not, see <http://www.gnu.org/licenses/>.",
			"",
			"#include </Derm/Shaders/Light/LightState>",
			"#include </Derm/Shaders/Light/MaterialState>",
			"",
			"// @BeginInterface",
			"",
			"vec4 ComputeLightShading(ds_MaterialType material, vec4 eyePosition, vec3 normal);",
			"",
			"// @EndInterface",
			"",
			"vec4 ComputeLightShading(ds_MaterialType material, vec4 eyePosition, vec3 normal)",
			"{",
			"	vec4 lightAmbient = vec4(0.0), lightDiffuse = vec4(0.0);",
			"",
			"	// Lambert equation:",
			"	//",
			"	// color =	<emission> +",
			"	//			<ambient> * al +",
			"	//			<diffuse> * max(N . L, 0) +",
			"	// ",
			"	// Where:",
			"	// - al: ambient lighting",
			"	// - N: normal vector",
			"	// - L: light vector",
			"",
			"	ComputeLightContributions(normal, eyePosition, lightAmbient, lightDiffuse);",
			"",
			"	return (",
			"		material.EmissiveColor + ds_LightModel.AmbientLighting +",
			"		material.DiffuseColor * lightDiffuse",
			"		);",
			"}",
		};

		#endregion
	}

	/// <summary>
	/// Shader source generated from PhongShading shader source file.
	/// </summary>
	public class PhongShading : ShaderObject
	{
		#region Constructors

		/// <summary>
		/// Construct a PhongShading specifying the shader stage.
		/// </summary>
		/// <param name="sType">
		/// A <see cref="Stage"/> indicating the shader stage of this PhongShading.
		/// </param>
		public PhongShading(Stage sType) : base(sType, "Derm/Shaders/Light/PhongShading") { }

		/// <summary>
		/// A string that identifies this ShaderObject implementation in ShaderLibraryConfiguration.
		/// </summary>
		public static readonly string LibraryId = "Derm.Light.PhongShading";

		#endregion

		#region ShaderObject Overrides

		/// <summary>
		/// The source string read from Derm/Shaders/Light/PhongShading.
		/// </summary>
		protected override string[] Source { get { return (sShaderSource); } }

		/// <summary>
		/// The source string read from Derm/Shaders/Light/PhongShading.
		/// </summary>
		private static readonly string[] sShaderSource = new string[] {
			"",
			"//  Copyright (C) 2012 Luca Piccioni",
			"// ",
			"//  This program is free software: you can redistribute it and/or modify",
			"//  it under the terms of the GNU General Public License as published by",
			"//  the Free Software Foundation, either version 3 of the License, or",
			"//  (at your option) any later version.",
			"// ",
			"//  This program is distributed in the hope that it will be useful,",
			"//  but WITHOUT ANY WARRANTY; without even the implied warranty of",
			"//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the",
			"//  GNU General Public License for more details.",
			"// ",
			"//  You should have received a copy of the GNU General Public License",
			"//  along with this program.  If not, see <http://www.gnu.org/licenses/>.",
			"",
			"#include </Derm/Shaders/Light/LightState>",
			"#include </Derm/Shaders/Light/MaterialState>",
			"",
			"// @BeginInterface",
			"",
			"vec4 ComputeLightShading(ds_MaterialType material, vec4 eyePosition, vec3 normal);",
			"",
			"// @EndInterface",
			"",
			"vec4 ComputeLightShading(ds_MaterialType material, vec4 eyePosition, vec3 normal)",
			"{",
			"	vec4 lightAmbient = vec4(0.0), lightDiffuse = vec4(0.0), lightSpecular = vec4(0.0);",
			"",
			"	// Phong equation:",
			"	//",
			"	// color =	<emission> +",
			"	//			<ambient> * al +",
			"	//			<diffuse> * max(N . L, 0) +",
			"	//			<specular> * max(R . I, 0) ^ <shininess>",
			"	// ",
			"	// Where:",
			"	// - al: ambient lighting",
			"	// - N: normal vector",
			"	// - L: light vector",
			"	// - I: eye vector",
			"	// - R: perfect reflection vector (reflect(L around N))",
			"",
			"	ComputeLightContributions(normal, eyePosition, material.Shininess, lightAmbient, lightDiffuse, lightSpecular);",
			"",
			"	return (",
			"		material.EmissiveColor +",
			"		ds_LightModel.AmbientLighting * lightAmbient +",
			"		material.DiffuseColor * lightDiffuse +",
			"		material.SpecularColor * lightSpecular",
			"		);",
			"}",
		};

		#endregion
	}

	/// <summary>
	/// Shader source generated from BlinnShading shader source file.
	/// </summary>
	public class BlinnShading : ShaderObject
	{
		#region Constructors

		/// <summary>
		/// Construct a BlinnShading specifying the shader stage.
		/// </summary>
		/// <param name="sType">
		/// A <see cref="Stage"/> indicating the shader stage of this BlinnShading.
		/// </param>
		public BlinnShading(Stage sType) : base(sType, "Derm/Shaders/Light/BlinnShading") { }

		/// <summary>
		/// A string that identifies this ShaderObject implementation in ShaderLibraryConfiguration.
		/// </summary>
		public static readonly string LibraryId = "Derm.Light.BlinnShading";

		#endregion

		#region ShaderObject Overrides

		/// <summary>
		/// The source string read from Derm/Shaders/Light/BlinnShading.
		/// </summary>
		protected override string[] Source { get { return (sShaderSource); } }

		/// <summary>
		/// The source string read from Derm/Shaders/Light/BlinnShading.
		/// </summary>
		private static readonly string[] sShaderSource = new string[] {
			"",
			"//  Copyright (C) 2012 Luca Piccioni",
			"// ",
			"//  This program is free software: you can redistribute it and/or modify",
			"//  it under the terms of the GNU General Public License as published by",
			"//  the Free Software Foundation, either version 3 of the License, or",
			"//  (at your option) any later version.",
			"// ",
			"//  This program is distributed in the hope that it will be useful,",
			"//  but WITHOUT ANY WARRANTY; without even the implied warranty of",
			"//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the",
			"//  GNU General Public License for more details.",
			"// ",
			"//  You should have received a copy of the GNU General Public License",
			"//  along with this program.  If not, see <http://www.gnu.org/licenses/>.",
			"",
			"#include </Derm/Shaders/Light/LightState>",
			"#include </Derm/Shaders/Light/MaterialState>",
			"",
			"// @BeginInterface",
			"",
			"vec4 ComputeBlinnPhongShading(ds_MaterialType material, vec3 normal);",
			"",
			"// @EndInterface",
			"",
			"vec4 ComputeBlinnPhongShading(ds_MaterialType material, vec3 normal)",
			"{",
			"	vec4 lightAmbient = vec4(0.0), lightDiffuse = vec4(0.0), lightSpecular = vec4(0.0);",
			"",
			"	// Phong equation:",
			"	//",
			"	// color =	<emission> +",
			"	//			<ambient> * al +",
			"	//			<diffuse> * max(N . L, 0) +",
			"	//			<specular> * max(N . H, 0) ^ <shininess>",
			"	// ",
			"	// Where:",
			"	// - al: ambient lighting",
			"	// - N: normal vector",
			"	// - L: light vector",
			"	// - I: eye vector",
			"	// - H: half-angle vectors, (normalize(I+L))",
			"",
			"	ComputeLightContributions(normal, lightAmbient, lightDiffuse, lightSpecular);",
			"",
			"	return (",
			"		material.Emission +",
			"		material.Ambient  * lightAmbient * ds_LightModel.AmbientLighting +",
			"		material.Diffuse  * lightDiffuse +",
			"		material.Specular * lightSpecular",
			"		);",
			"}",
		};

		#endregion
	}

	/// <summary>
	/// Shader include extracted from ILightShading.
	/// </summary>
	public class ILightShading : ShaderInclude
	{
		#region Constructors

		/// <summary>
		/// Construct a ILightShading.
		/// </summary>
		public ILightShading() : base("/Derm/Shaders/Light/ILightShading", sShaderInclude) { }

		#endregion

		#region ShaderInclude Source Code

		/// <summary>
		/// The shader include source code.
		/// </summary>
		private static readonly string[] sShaderInclude = new string[] {
			"#include </Derm/Shaders/Light/MaterialState>\n",
			"/// <summary>\n",
			"/// Compute a light contribution combining ambient, diffuse and specular components.\n",
			"/// <summary/>\n",
			"vec4 ComputeLightShading(ds_MaterialType material, vec4 eyePosition, vec3 normal);\n",
			"/// <summary>\n",
			"/// Compute a light contribution combining ambient and diffuse components.\n",
			"/// <summary/>\n",
			"vec4 ComputeLightShadingDiffuse(ds_MaterialType material, vec3 normal);\n",
			"/// <summary>\n",
			"/// Compute a light contribution combining only specular components.\n",
			"/// <summary/>\n",
			"vec4 ComputeLightShadingSpecular(ds_MaterialType material, vec3 normal);\n",
		};

		#endregion
	}

	/// <summary>
	/// Shader include extracted from MaterialState.
	/// </summary>
	public class IMaterialStateShader : ShaderInclude
	{
		#region Constructors

		/// <summary>
		/// Construct a IMaterialStateShader.
		/// </summary>
		public IMaterialStateShader() : base("/Derm/Shaders/Light/MaterialState", sShaderInclude) { }

		#endregion

		#region ShaderInclude Source Code

		/// <summary>
		/// The shader include source code.
		/// </summary>
		private static readonly string[] sShaderInclude = new string[] {
			"#ifndef _DERM_MATERIAL_STATE_\n",
			"#define _DERM_MATERIAL_STATE_\n",
			"// Common material type\n",
			"struct ds_MaterialType\n",
			"{\n",
			"// Material emissive color.\n",
			"vec4 EmissiveColor;\n",
			"// Material diffuse color.\n",
			"vec4 DiffuseColor;\n",
			"// Material emissive color.\n",
			"vec4 SpecularColor;\n",
			"// Material shininess.\n",
			"float Shininess;\n",
			"};\n",
			"// Textured material.\n",
			"struct ds_TexMaterialType\n",
			"{\n",
			"// Texture used for diffuse color\n",
			"sampler2D DiffuseTexture;\n",
			"// Texture coordinates used for DiffuseTexture\n",
			"int DiffuseTexCoord;\n",
			"};\n",
			"// The front face material\n",
			"uniform ds_MaterialType ds_FrontMaterial;\n",
			"// The front face material, textured\n",
			"uniform ds_TexMaterialType ds_FrontTexMaterial;\n",
			"#endif /* _DERM_MATERIAL_STATE_ */\n",
		};

		#endregion
	}

}

